package com.ums.scumspay.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ums.scumspay.constant.MerInfoConstant;
import com.ums.scumspay.constant.UrlConstant;
import com.ums.scumspay.entity.PayOrder;
import com.ums.scumspay.entity.PayQueryReq;
import com.ums.scumspay.entity.ProdModel;
import com.ums.scumspay.entity.req.PayCrtReq;
import com.ums.scumspay.entity.req.RefundReq;
import com.ums.scumspay.entity.resp.PayResp;
import com.ums.scumspay.service.*;
import com.ums.scumspay.utils.RandomUtils;
import com.ums.scumspay.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class PayCreateServiceImpl implements PayCreateService {

    @Autowired
    private PayOrderService payOrderService;

    @Autowired
    private BtoCService btoCService;

    @Autowired
    private CtoBService ctoBService;

    @Autowired
    private H5PayService h5PayService;


    @Override
    public PayResp b2cPay(PayCrtReq payCrtReq) {
        Double prodAmt = 0.0;
        if (payCrtReq.getProdModel() != null) {
            for (ProdModel prodModel : payCrtReq.getProdModel()) {
                if (prodModel.getNum() == 0) {
                    prodAmt += prodModel.getPayAmt();
                } else {
                    prodAmt += prodModel.getPayAmt() * prodModel.getNum();
                }
            }
        }
        String orderNo = UUIDUtil.getUUID();
        String extOrderNo = "8888" + new SimpleDateFormat("yyyyMMddmmHHssSSS").format(new Date()) + RandomUtils.getRandomNum(7);
        PayOrder payOrder = new PayOrder();
        payOrder.setOrderNo(orderNo);
        payOrder.setTransNo(extOrderNo);
        payOrder.setMerNo(MerInfoConstant.mid);
        payOrder.setTermNo(MerInfoConstant.tid);
        payOrder.setTransType("1");
        payOrder.setPayMethod("0");
        // payOrder.setRefundSign("0");
        payOrder.setPayStatus("01");
        payOrder.setTransDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        payOrder.setTransTime(new SimpleDateFormat("HH:mm:ss").format(new Date()));
        payOrder.setProdAmt(prodAmt);
        payOrder.setTransAmt(prodAmt);
        payOrder.setProdModel(JSONUtil.toJsonStr(payCrtReq.getProdModel()));
        payOrder.setRemark("POS");
        payOrder.setName(payCrtReq.getName());
        payOrder.setPhone(payCrtReq.getPhone());
        payOrder.setIsBankCar(payCrtReq.getIsBankCar());
        payOrderService.save(payOrder);
        Boolean aBoolean = btoCService.sendPayRequest(extOrderNo, String.valueOf(prodAmt), payCrtReq.getIsBankCar());
        if (aBoolean) {
            return PayResp.builder().extOrderNo(extOrderNo).build();
        } else {
            return null;
        }
    }

    @Override
    public PayResp c2bPay(PayCrtReq payCrtReq) {
        Double prodAmt = 0.0;
        if (payCrtReq.getProdModel() != null) {
            for (ProdModel prodModel : payCrtReq.getProdModel()) {
                if (prodModel.getNum() == 0) {
                    prodAmt += prodModel.getPayAmt();
                } else {
                    prodAmt += prodModel.getPayAmt() * prodModel.getNum();
                }
            }
        }
        int amt = (int) (prodAmt * 100);
        String orderNo = UUIDUtil.getUUID();
        String extOrderNo = "8888" + new SimpleDateFormat("yyyyMMddmmHHssSSS").format(new Date()) + RandomUtils.getRandomNum(7);
        PayOrder payOrder = new PayOrder();
        payOrder.setOrderNo(orderNo);
        payOrder.setTransNo(extOrderNo);
        payOrder.setMerNo(MerInfoConstant.mid);
        payOrder.setTermNo(MerInfoConstant.tid);
        payOrder.setTransType("2");
        payOrder.setPayMethod("1");
        // payOrder.setRefundSign("0");
        payOrder.setPayStatus("01");
        payOrder.setTransDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        payOrder.setTransTime(new SimpleDateFormat("HH:mm:ss").format(new Date()));
        payOrder.setProdAmt(prodAmt);
        payOrder.setTransAmt(prodAmt);
        payOrder.setProdModel(JSONUtil.toJsonStr(payCrtReq.getProdModel()));
        payOrder.setRemark("静态码");
        payOrder.setName(payCrtReq.getName());
        payOrder.setPhone(payCrtReq.getPhone());
        payOrderService.save(payOrder);
        String resp = ctoBService.sendPayRequest(extOrderNo, String.valueOf(amt));
        return PayResp.builder().extOrderNo(extOrderNo).qrCode(resp).build();
    }

    @Override
    public String h5Pay(PayCrtReq payCrtReq) {
        int prodAmt = 0;
        if (payCrtReq.getProdModel() != null) {
            for (ProdModel prodModel : payCrtReq.getProdModel()) {
                if (prodModel.getNum() == 0) {
                    prodAmt += prodModel.getPayAmt();
                } else {
                    prodAmt += prodModel.getPayAmt() * prodModel.getNum();
                }
            }
        }
        String orderNo = UUIDUtil.getUUID();
        String extOrderNo = "8888" + new SimpleDateFormat("yyyyMMddmmHHssSSS").format(new Date()) + RandomUtils.getRandomNum(7);
        PayOrder payOrder = new PayOrder();
        payOrder.setOrderNo(orderNo);
        payOrder.setTransNo(extOrderNo);
        payOrder.setMerNo(MerInfoConstant.mid);
        payOrder.setTermNo(MerInfoConstant.tid);
        payOrder.setTransType("3");
        payOrder.setPayMethod("1");
        // payOrder.setRefundSign("0");
        payOrder.setPayStatus("01");
        payOrder.setTransDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        payOrder.setTransTime(new SimpleDateFormat("HH:mm:ss").format(new Date()));
        payOrder.setProdAmt(prodAmt / 100.0);
        payOrder.setTransAmt(prodAmt / 100.0);
        payOrder.setProdModel(JSONUtil.toJsonStr(payCrtReq.getProdModel()));
        payOrder.setRemark("静态码");
        payOrder.setName(payCrtReq.getName());
        payOrder.setPhone(payCrtReq.getPhone());
        payOrderService.save(payOrder);
        String resp = h5PayService.sendPayRequest(extOrderNo, String.valueOf(prodAmt), "zfb");
        return resp;
    }

    @Override
    public String b2cQuery(PayQueryReq req) {
        if (req.getExtOrderNo().length() < 6 || req.getExtOrderNo().length() > 31) {
            return "参数长度不合法，必须介于6至31之间";
        }
        Map<String, String> map = btoCService.sendQueryPayResult(req.getExtOrderNo());
        List<PayOrder> one = payOrderService.list(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, req.getExtOrderNo()));
        if (map != null && map.containsKey("tradeCode") && map.get("tradeCode").equals("00") && one.get(0).getPayStatus().equals("00") && one.size() != 2) {
            return "00";
        } else if (map != null && map.containsKey("tradeCode") && map.get("tradeCode").equals("00") && one.size() == 2) {
            return "02";
        } else if (map != null && map.containsKey("tradeCode") && map.get("tradeCode").equals("FK")) {
            return "04";
        } else if (map != null && map.get("errCode").equals("902035")) {
            return "05";
        } else if (map != null && map.containsKey("tradeCode") && map.get("tradeCode").equals("FJ")) {
            return "06";
        } else {
            return "01";
        }

    }

    @Override
    public String c2bQuery(PayQueryReq req) {
        if (req.getExtOrderNo().length() < 6 || req.getExtOrderNo().length() > 31) {
            return "参数长度不合法，必须介于6至31之间";
        }
        Map<String, String> map = ctoBService.sendQueryPayResult(req.getExtOrderNo());
        if (map != null && map.get("errCode").equals("SUCCESS") && map.containsKey("billStatus") && map.get("billStatus").equals("PAID")) {
            return "00";
        } else if (map != null && map.get("errCode").equals("SUCCESS") && map.containsKey("billStatus") && map.get("billStatus").equals("REFUND")) {
            return "02";
        } else if (map != null && map.containsKey("tradeCode") && map.get("tradeCode").equals("FK")) {
            return "04";
        } else if (map != null && map.get("errCode").equals("NO_BILL")) {
            return "05";
        } else {
            return "01";
        }
    }

    @Override
    public String h5Query(PayQueryReq req) {
        Map<String, String> map = h5PayService.sendQueryPayResult(req.getExtOrderNo());
        // return map.get("status").equals("TRADE_SUCCESS");
        return null;
    }

    @Override
    public Boolean b2cRefund(RefundReq req) {
        String transNo="8888" + new SimpleDateFormat("yyyyMMddmmHHssSSS").format(new Date()) + RandomUtils.getRandomNum(7);
        PayOrder payOrder = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, req.getExtOrderNo()));
        List<PayOrder> list = payOrderService.list(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderNo, payOrder.getOrderNo()));
        if (list!=null && list.size() == 1) {
            PayOrder one = list.get(0);
            one.setId(null);
            one.setTransNo(transNo);
            one.setPayStatus("01");
            one.setRefundSign("1");
            payOrderService.save(one);
        }

        Boolean b = btoCService.sendCancelRequest(req.getExtOrderNo(), req.getProofNo());
        return b;
    }

    @Override
    public Boolean c2bRefund(RefundReq req) {

        PayOrder payOrder = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, req.getExtOrderNo()));
        List<PayOrder> list = payOrderService.list(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderNo, payOrder.getOrderNo()));
        if (list!=null && list.size() == 1) {
            PayOrder one = list.get(0);
            one.setId(null);
            one.setTransNo("8888" + new SimpleDateFormat("yyyyMMddmmHHssSSS").format(new Date()) + RandomUtils.getRandomNum(7));
            one.setPayStatus("01");
            one.setRefundSign("1");
            payOrderService.save(one);
        }

        Map<String,String> map = ctoBService.sendCancelRequest(req.getExtOrderNo(), req.getPayAmount());
        // if (map!=null && map.get("errCode").equals("HAS_REFUNDED")){
        //     PayOrder order1 = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
        //     PayOrder one2 = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderNo, order1.getOrderNo()).eq(PayOrder::getRefundSign, 1));
        //     one2.setPayStatus("02");
        //     payOrderService.updateById(one2);
        // }
        if (map!=null && map.containsKey("billStatus") && map.get("billStatus").equals("REFUND")){
            return true;
        }else if (map!=null && map.containsKey("errCode") && map.get("errCode").equals("HAS_REFUNDED")){
            return true;
        }

        return false;
    }

    @Override
    public Boolean h5Refund(RefundReq req) {
        PayOrder payOrder = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, req.getExtOrderNo()));
        List<PayOrder> list = payOrderService.list(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderNo, payOrder.getOrderNo()));
        if (list.size() == 1) {
            PayOrder one = list.get(0);
            one.setId(null);
            one.setTransNo("8888" + new SimpleDateFormat("yyyyMMddmmHHssSSS").format(new Date()) + RandomUtils.getRandomNum(7));
            one.setPayStatus("01");
            one.setRefundSign("1");
            payOrderService.save(one);
        }
        Boolean b = h5PayService.sendCancelRequest(req.getExtOrderNo(), req.getPayAmount());
        return b;
    }

    @Override
    public void urlNotify(String extOrderNo) {
        String[] split = extOrderNo.split("-");
        String s = split[0];
        log.info("回调启动");
        switch (split[1]) {
            case "11":
                log.info("11");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                Map<String, String> map = btoCService.sendQueryPayResult(s);
                if (map != null && map.get("tradeCode").equals("00")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setRefundSign("0");
                    one.setPayStatus("00");
                    one.setProof(map.get("traceNo"));
                    payOrderService.updateById(one);
                } else if (map != null && map.get("tradeCode").equals("FK")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setPayStatus("04");
                    payOrderService.updateById(one);
                } else if (map != null && map.get("tradeCode").equals("FJ")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setPayStatus("06");
                    payOrderService.updateById(one);
                }
                break;
            case "12":
                log.info("12");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                Map<String, String> map3 = btoCService.sendQueryPayResult(s);
                if (map3 != null && map3.get("tradeCode").equals("00")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setRefundSign("0");
                    one.setPayStatus("00");
                    one.setProof(map3.get("traceNo"));
                    payOrderService.updateById(one);
                } else if (map3 != null && map3.get("tradeCode").equals("FK")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setPayStatus("04");
                    payOrderService.updateById(one);
                }
                break;
            case "13":
                log.info("13");
                Map<String, String> map4 = btoCService.sendQueryPayResult(s);
                if (map4 != null && map4.get("tradeCode").equals("00")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setRefundSign("0");
                    one.setPayStatus("00");
                    one.setProof(map4.get("traceNo"));
                    payOrderService.updateById(one);
                } else if (map4 != null && map4.get("tradeCode").equals("FK")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setPayStatus("04");
                    one.setProof(map4.get("traceNo"));
                    payOrderService.updateById(one);
                }
                break;
            case "2":
                log.info("2");
                Map<String, String> map1 = ctoBService.sendQueryPayResult(s);
                if (map1 != null && map1.get("billStatus").equals("PAID")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setRefundSign("0");
                    one.setPayStatus("00");
                    payOrderService.updateById(one);
                } else if (map1 != null && map1.get("billStatus").equals("CLOSED")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setPayStatus("04");
                    one.setProof(map1.get("traceNo"));
                    payOrderService.updateById(one);
                } else if (map1 != null && map1.get("billStatus").equals("REFUND")) {
                    PayOrder order1 = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    PayOrder one2 = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderNo, order1.getOrderNo()).eq(PayOrder::getRefundSign, 1));
                    one2.setPayStatus("02");
                    payOrderService.updateById(one2);
                }
                break;
            case "3":
                log.info("3");
                Map<String, String> map2 = h5PayService.sendQueryPayResult(s);
                if (map2 != null && map2.get("status").equals("TRADE_SUCCESS")) {
                    PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                    one.setRefundSign("0");
                    one.setPayStatus("00");
                    payOrderService.updateById(one);
                }
                break;
            case "5":
                log.info("5");
                PayOrder order = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, s));
                PayOrder one1 = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderNo, order.getOrderNo()).eq(PayOrder::getRefundSign, 1));
                Map<String, String> map5 = btoCService.sendQueryPayResult(s);
                if (map5 != null && map5.get("tradeCode").equals("00") ) {
                    one1.setPayStatus("02");
                    payOrderService.updateById(one1);
                }
                break;
        }
    }

    @Override
    public String querPayStatus(String extOrderNo) {
        PayOrder one = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTransNo, extOrderNo));
        if (one == null) {
            return "交易不存在";
        }
        return one.getPayStatus();
    }
}
